var GBK = null;
var IP_RECORD_LENGTH = 7,
	REDIRECT_MODE_1 = 0x01,
	REDIRECT_MODE_2 = 0x02,
	IP_REGEXP = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
var dbug = false, log = console.log,
	pathDefined = __dirname + "/qqwry.dat", //IP库默认路径
	ipBegin,ipEnd,ipCount,
	ipFileBuffer = null,uninfo = true,
	unArea ="未知地区",unCountry = "未知国家";

exports.DBUG = function(a){ dbug = a != undefined ? a : true; return this;}

exports.info = function(dataPath) {
	var fs = require('fs'),
		Path = typeof(dataPath) == "string" ? dataPath : pathDefined;
	var callback = typeof arguments[arguments.length-1] == "function" ? arguments[arguments.length-1] : function(){};
	GBK = require("./gbk.js");
	ipFileBuffer = fs.readFileSync(Path); //缓存IP库文件;
	ipBegin = ipFileBuffer.readUInt32LE(0,true); //索引的开始位置;
	ipEnd = ipFileBuffer.readUInt32LE(4,true); //索引的结束位置;
	ipCount = (ipEnd-ipBegin) / 7 + 1;
	dbug && log("==== Lib-qqwry Start! ==== [Begin:" + ipBegin + " End:" + ipEnd + " Count:" + ipCount + "]");
	uninfo = false;
	callback();
	return this;
}

//查询IP的地址信息
exports.searchIP = function(IP){
	uninfo && uninfo();
	var ip = this.ipToInt(IP),
		g = LocateIP(ip),
		loc={};
	if(g == -1){return {"ip":IP,"Country":unArea,"Area":unCountry};}
	var add = setIPLocation(g);
	loc.ip = this.intToIP(ip);
	loc.Country = add.Country;
	loc.Area = add.Area;
	dbug && log(loc);
	return loc;
}

//查询IP段的地址信息;scope
exports.searchIPScope = function(bginIP,endIP,callback){
	uninfo && uninfo();
	var _ip1,_ip2,b_g,e_g,ips=[];
	try{_ip1 = this.ipToInt(bginIP);}catch(e){throw ("The bginIP is not normal! >> " + bginIP);}
	try{_ip2 = this.ipToInt(endIP);}catch(e){throw ("The endIP is not normal! >> " + endIP);}
	b_g = LocateIP(_ip1);
	e_g = LocateIP(_ip2);
	for(var i = b_g; i<= e_g ; i+= IP_RECORD_LENGTH){
		var loc = {},add = setIPLocation(i);
		loc.begIP = this.intToIP(ipFileBuffer.readUInt32LE(i,true));
		loc.endIP = this.intToIP(ipFileBuffer.readUInt32LE(setBuffer3(i+4),true));
		loc.Country = add.Country;
		loc.Area = add.Area;
		ips.push(loc);
	}
	if(typeof callback === "function"){callback(ips);}
	return ips;
}

//ip地址转int
exports.ipToInt = function(IP){
	var result = IP_REGEXP.exec(IP),ip;
	if(result){
		var ip_Arr = result.slice(1);
		ip =(parseInt(ip_Arr[0]) << 24 
			| parseInt(ip_Arr[1]) << 16
			| parseInt(ip_Arr[2]) << 8
			| parseInt(ip_Arr[3])) >>> 0;
	}else if(/^\d+$/.test(IP) && (ip=parseInt(IP))>=0 && ip <= 0xFFFFFFFF ){
	
	}else{
		throw ("The IP address is not normal! >> " + IP);
	}
	return ip;
}

//int转ip地址
exports.intToIP = function(INT){
	if(INT < 0 || INT > 0xFFFFFFFF){
		throw ("The number is not normal! >> " + INT);
	};
	return (INT>>>24) + "." + (INT>>>16 & 0xFF) + "." + (INT>>>8 & 0xFF) + "." + (INT>>>0 & 0xFF);
}

//IP数值高低字节位切换
exports.ipEndianChange = function(INT){
	INT = INT & 0xFFFFFFFF;
	return (INT >>> 24 | (INT >> 8 & 0xFF00) | (INT << 8 & 0xFF0000) | (INT << 24)) >>> 0;
}

exports.infoAsync = function(){
	var o = this,args = arguments;
	setTimeout(function(){o.info.apply(o,args)});
	return this;
}

exports.searchIPScopeAsync = function(a,b,c){
	var o = this;
	setTimeout(function(){o.searchIPScope(a,b,c)});
	return this;
}

//查找地址信息
function setIPLocation(g){
	var ipwz = setBuffer3(g+4) + 4;
	var lx = ipFileBuffer.readUInt8(ipwz),
		loc={};
	if(lx == REDIRECT_MODE_1){//Country根据标识再判断
        ipwz = setBuffer3(ipwz+1); //读取国家偏移
		lx = ipFileBuffer.readUInt8(ipwz); //再次获取标识字节
		var Gjbut;
		if (lx == REDIRECT_MODE_2){//再次检查标识字节
			Gjbut = setIpFileString(setBuffer3(ipwz+1));
			loc.Country = GBK.dc_GBK(Gjbut);
            ipwz = ipwz + 4;
		}else{
			Gjbut = setIpFileString(ipwz)
			loc.Country = GBK.dc_GBK(Gjbut);
            ipwz += Gjbut.length + 1;
		}
		loc.Area = ReadArea(ipwz);
	}else if(lx == REDIRECT_MODE_2){//Country直接读取偏移处字符串
		var Gjbut = setIpFileString(setBuffer3(ipwz+1));
		loc.Country = GBK.dc_GBK(Gjbut);
		loc.Area = ReadArea(ipwz + 4);
	}else{//Country直接读取 Area根据标志再判断
		var Gjbut = setIpFileString(ipwz);
		ipwz += Gjbut.length + 1;
		loc.Country = GBK.dc_GBK(Gjbut);
		loc.Area = ReadArea(ipwz);
	}
	return loc;
}

//读取Area
function ReadArea(offset){
	var one = ipFileBuffer.readUInt8(offset);
	if (one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2) {
		var areaOffset = setBuffer3(offset + 1);
		if (areaOffset == 0)
			return unArea;
		else {
			return GBK.dc_GBK(setIpFileString(areaOffset));
		}
	} else {
		return GBK.dc_GBK(setIpFileString(offset));
	}
}

//获取3字节的索引地址;
function setBuffer3(n){
	return ipFileBuffer.readUInt32LE(n,true) & 0xFFFFFF;
}

//(拼接的Buffer中)读取字节,直到为0x00结束,返回数组
function setIpFileString(Begin){
	var B = Begin || 0,toarr = [], M = ipFileBuffer.length;
	B = B < 0 ? 0 : B;
	for(var i = B ; i < M ;i++){
		if(ipFileBuffer[i] == 0){
			return toarr;
		}
		toarr.push(ipFileBuffer[i]);
	}
	return toarr;
}

// 取得begin和end中间的偏移(用于2分法查询);
function GetMiddleOffset(begin, end ,recordLength) {
	var records = ( (end - begin) / recordLength >> 1 ) * recordLength + begin; 
	return records ^ begin ? records : records + recordLength;
}

//2分法查找指定的IP偏移
function LocateIP(ip){
	var g,temp;
	for (var b=ipBegin,e=ipEnd;b<e;){
		g = GetMiddleOffset(b,e,IP_RECORD_LENGTH);//获取中间位置
		temp = ipFileBuffer.readUInt32LE(g,true);
		if(ip>temp){
			b = g;
		}else if(ip<temp){
			if(g == e){
				g -= IP_RECORD_LENGTH;
				break;
			}
			e = g;
		}else{
			break;
		}
	}
	if(dbug){
		var begip = ipFileBuffer.readUInt32LE(g,true);
			endip = ipFileBuffer.readUInt32LE(setBuffer3(g+4),true); //获取结束IP的值
		log(exports.intToIP(ip) + " >> " + ip);
		log(">> Indexes as \"" + g + "\" ( " + begip + " --> " + endip + " )");
		if(ip>endip){//与结束IP比较；正常情况不会出现这种情况,除非IP库漏掉了一些IP;
			return -1;
		}
	}
	return g;
}

//未初始化
function uninfo(){
	throw ("The lib-qqwry is Uninitialized!");
}
